#ifndef _CEDITBOX_H_
#define _CEDITBOX_H_

#include <buola/widgets/cwidget.h>

#include <buola/utility/uevent.h>
#include <buola/image/ctextlayout.h>

namespace buola { namespace gui {

class CEditBox : public CWidget
{
public:
    enum
    {
        STYLE_NUMERIC=(1<<8),
        STYLE_DOUBLE=(1<<9),
        STYLE_MULTILINE=(1<<10),
        STYLE_CENTER=(1<<11)
    };

    class SCompleter
    {
    public:
        virtual ~SCompleter() {}

        virtual void GetCompletionOptions(std::vector<std::wstring> &pList,
                            CEditBox *pEditBox,const std::wstring &pText)=0;
    };

    CEditBox();
    virtual ~CEditBox();

    virtual void GetPropertyNames(std::vector<std::string> &pNames);
    virtual void SetProperty(const std::string &p,const UAny&);

    void SetCompleter(SCompleter*);
    void DoComplete();
    void StopComplete();

////////////// Functions for theme drawing /////////////
    img::CTextLayout &GetTextLayout()                    {   return mLayout;     }
    const img::CTextLayout::SCursor &GetTextCursor()     {   return mCursor;     }

////////////// Event handling //////////////
    virtual void OnDestroy();
    virtual void OnExpose(const CExposeEvent &pE);
    virtual void OnButtonDown(const CMouseEvent &pE);
    virtual void OnButtonUp(const CMouseEvent &pE);
    virtual void OnMouseMove(const CMouseEvent &pE);
    virtual void OnFocusIn(const CFocusEvent &pE);
    virtual void OnFocusOut(const CFocusEvent &pE);
    virtual void OnChar(const CKeyEvent &pE);
    virtual void OnKeyDown(const CKeyEvent &pE);
    virtual void OnSize(const CGeometryEvent &pE);
    virtual void OnStyleChanged(TStyle);
    virtual void OnEnter();

    void OnTimer();

public:
////////////////// interface //////////////////////
    void SelectAll();
    void Insert(const std::wstring&);
    void Insert(wchar_t);
    void EraseSelection();
    void EraseChar(bool pBack);

    void SetFont(img::PFont );

    //! sets the caption to display for the box
    void SetCaption(const std::wstring &pCaption=std::wstring());
    
    //! returns the caption to display for the box
    const std::wstring &GetCaption()    {   return mCaption;    }
    
public:
////////////// protected functions ////////////////
    void MoveCursorTo(const img::CTextLayout::SCursor &pCursor);
    void ExtendSelectionTo(const img::CTextLayout::SCursor &pCursor);
    void MoveCursor(img::CTextLayout::ECursorMove,bool pSelect=false);

    void CalcAll();
    void CalcCursorPos();
    img::CTextLayout::SCursor CalcCursor(const CPoint_d &pPos);
    const img::CTextLayout::SCursor &GetCursor()     {   return mCursor; }

    void UpdateSelection();

    USignal<void(const std::wstring&)> sEndEditor;
    UEvent<void(std::wstring)> eEnter;
    UEvent<void()> eEscape;
    UEvent<void(bool)> eChange;
    UEvent<void()> eFocusLost;

    CPoint_d mScrollPos;
    CPoint_d mTextPos;
    CSize_d mTextSize;

    bool mCursorOn;

    int mSelStart;
    int mSelEnd;
    int mDragStart;

    bool mPressed;

    img::PFont mFont;

    std::unique_ptr<CTimer> mTimer;
    PListBox mCompleteList;

    SCompleter *mCompleter;

    img::CTextLayout mLayout;
    img::CTextLayout::SCursor mCursor;
    CRect_d mCursorPos;

    std::wstring mCaption;
};

/*namespace gui*/ } /*namespace buola*/ }

#endif
